<?php
/**
 * @file
 * Model is a facade for Db_Statement.
 *
 * @category   rpd
 * @package    Model
 * @subpackage Model
 * @copyright  Copyright (c) 2010 Rpd-Team (http://code.google.com/p/rpd)
 * @license    BSD License
 * @link       http://code.google.com/p/rpd/wiki/Model
 * @since      0.0.1
 * @version    0.0.1
 */

/**
 * Model class that represent statements / tables as array.
 *
 * Inherit from the model to generate representations of each table:
 *
 * @code
 *   class Model_Tablename extends Model
 *   {
 *     const DB = "foo"; // use the foo-connection from config
 *     const TABLE = "tablename"; // specify the represented table(s)
 *   }
 * @endcode
 *
 * Write "TABLE = 'table1, table_two';" if you want to merge multiple tables.
 *
 * The instance can be accessed like an array:
 *
 * @code
 *   $mdl = new Model_Tablename();
 *   $mdl[] = array('add' => 'this');
 *   echo $mdl[0]["row_name"];
 * @endcode
 *
 * This class facades the Db_Statement.
 * @see Db_Statement_Interface
 *
 *
 * @author pretzlaw
 */


class rpd_Model
	implements ArrayAccess,
	           Iterator

{
	/**
	 * Name of the databaseconfiguration
	 *
	 * @var String access data
	 */
	const DB = NULL;

	/**
	 * Name of the table(s) comaseperated
	 *
	 * @var String tablename
	 */
	const TABLE = "";

	/**
	 * internal connection to database
	 *
	 * @var Db
	 */
	private $_db = NULL;

	/**
	 * representation of the table / executed statement
	 *
	 * @var Db_Statement
	 */
	private $_stmt = NULL;

	/**
	 * list of rownames
	 *
	 * @var string
	 */
	private $_fields = NULL;

	/**
	 * choosen fields by constructor
	 *
	 * @var string
	 */
	private $_field = '';

	/**
	 * choosen whereclause by copnstructor
	 *
	 * @var string
	 */
	private $_where = '';

	/**
	 * @param offset
	 */
	public function offsetExists ($offset) {}

	/**
	 * get a special row or field of the statement
	 *
	 * @code
	 *   $mdl[] = new Model_Tablename();
	 *   echo $mdl[5]["row_name"];
	 * @endcode
	 *
	 * @param mixed offset
	 */
	public function offsetGet ($offset)
	{
		var_dump($this->_stmt);
		if (intval($offset) == $offset)
		{
			return Model_Single($this->_stmt, $offset);
		}
		else
		{
			return $this->_stmt[$offset];
		}
	}

	/**
	 * change a special row in the table
	 *
	 * $mdl[5] = array("row" => "value");
	 *
	 * $mdl[5]["row"] = "value";
	 *
	 * @param string offset the row num or fieldname
	 * @param string value  the new value
	 */
	public function offsetSet ($offset, $value)
	{
		if ($offset === NULL)
		{
			$a = array_intersect_key($value, $this->_stmt->fields());
			$sql = 'INSERT INTO `' . $this::TABLE . '` (`';
			$sql .= implode('`, `', array_keys($a)) . '`) VALUES (';
			$add = '';
			foreach ($a as $value)
			{
				$add .= ',' . $this->_db->quote($value);
			}
			$sql .= substr($add, 1) . ')';

			$this->_db->query($sql);
			echo mysql_error();
		}
		else if (isset($this->_current[$offset]))
		{
		}
	}

	/**
	 * Delete the choosen row
	 *
	 * @param offset Integer number of the row
	 */
	public function offsetUnset ($offset)
	{
		$a = $this->offsetGet($offset);
		foreach ($a as $key => $value)
		{
			$s .= "&& `". $key . "` = " . $this->_db->quote($value);
		}

		$s = "DELETE FROM `" . $this::TABLE . "` WHERE " . substr($s, 2);
		$this->_db->query($s);
	}

	/**
	 * get the current row of the represented statement
	 *
	 * @return ArrayObject current row
	 */
	public function current ()
	{
		return $this->_stmt->current();
	}

	/**
	 * switch to the next row and return it
	 *
	 * @return ArrayObject next row
	 */
	public function next ()
	{
		return $this->_stmt->next();
	}

	/**
	 * get the number of the current position in the table
	 *
	 * @return integer current row
	 */
	public function key ()
	{
		return $this->_stmt->key();
	}

	/**
	 * is the current row out of bounds (true / false)
	 *
	 * @return boolean valid row
	 */
	public function valid ()
	{
		if ($this->_stmt === false)
		{
			return false;
		}
		return $this->_stmt->valid();
	}

	/**
	 * go back to the first row
	 */
	public function rewind ()
	{
		if ($this->valid())
		{
			$this->_stmt->rewind();
		}
	}

	/**
	 * refresh the statement and therefore the instance too
	 */
	public function refresh()
	{
		unset($this->_stmt);
		$this->_stmt = $this->_db->query(
			'SELECT ' . $this->_field . ' FROM ' . $this::TABLE .
			' WHERE ' . $this->_where
		);
	}

	/**
	 * Constructor
	 *
	 * @param $where string condition for subset
	 * @param $field string selected columns
	 * @param $quote array  associated array to quote
	 */
	public function __construct($where = '1', $field = '*', $quote = NULL)
	{
		$this->_db = Db::get($this::DB);

		if (is_array($where))
		{
			$this->_where = '';
			foreach ($where as $key => $value)
			{
				$this->_where .= ' && `' . $key . '` = ' . $this->_db->quote($value);
			}
			$this->_where = substr($this->_where, 3);
		}
		else if ($where === false)
		{
			$this->_where = '1 LIMIT 1';
			$this->_field = $field;
		}
		else
		{
			$this->_where = $where;
			$this->_field = $field;
		}

		if ($quote !== NULL)
		{
			foreach($quote as $key => $value)
			{
				$this->_where = str_replace($key,
				                            $this->_db->quote($value),
				                            $this->_where);
			}
		}
		$this->refresh();
	}
}

if (!isset(Hook::$classes["Model"]))
{
	class Model extends rpd_Model {}
}